In case you have a website where each post or a custom post type, requires a featured image, there is a chance, the client might ignore that when publishing. In this tutorial, we’ll learn how to disable the publish/update button if there is no featured image added.

We will do this by using vanilla JavaScript (no React needed) so you can use this code without needing any compiling. You can put the code we will write inside of a plugin or theme.

How to know if there is a Feature Image

To know if there is a featured image, we will use the @wordpress/data that is available globally as wp.data. This is the state manager from which we can access different data.

This part involved a lot of trial and error to find the correct store and the correct setting. What I’ve done to make it a little bit easier was finding the classes around the features image. Then I searched for it inside of the WordPress Block Editor code and then tried to find out how they accessed and knew if there was a featured image.

To find out the featured image ID, you can use this:

var imageId = wp.data.select( 'core/editor' ).getEditedPostAttribute('featured_media');

We access the store core/editor and then get the attribute featured_media.

How to disable the publish/editor button

Inside of the WordPress Block Editor, the publish button can be disabled also through the wp.data. That’s done by dispatching (or in other words, calling methods registered inside of the specific store).

Here is how we can disable the button:

wp.data.dispatch('core/editor').lockPostSaving('noFeaturedImage');

The string noFeaturedImage is passed so when we unlock it, it will unlock for that string. I haven’t investigated too much, but my guess is that the string is used so we can’t unlock it if the button was locked by a different string (so we don’t unlock it while something else is also locking it). Could be wrong, so please do let me know in the comments.

If we can lock the saving of a post, we can also unlock it:

wp.data.dispatch( 'core/editor' ).unlockPostSaving( 'noFeaturedImage' );

How to know if a featured image was added or removed

I haven’t gone too much in-depth of how we could specifically know if such event was triggered, but I did find out there is a subscribe method. This will be called each time something has changed inside of the store manager (wp.data). This is done like this:

wp.data.subscribe(function(){
  // Do something when state data changes.
});

Conditionally Disabling the Publish/Update Button

Let’s now put everything together. First, the PHP part (which you might skip if you have a JavaScript file loaded when the WordPress Block Editor loads).

<?php

add_action( 'admin_footer', 'disable_publish_button_if_no_featured_image' );

/**
 * Loads inside of the Admin Footer only if we are on a post.
 * Disables the Publish button if no featured image is set.
 */
function disable_publish_button_if_no_featured_image() {
   global $post;
    
   // No post, skip.
	if ( ! $post ) {
		return;
	}

    // Different post type? Skip.
	if ( 'post' !== get_post_type( $post ) ) {
		return;
	}

   // You could also use something like WP_Screen::is_block_editor() to check if Block Editor is loaded.
   
   ?>
    <script defer>
     // Next code will go here.
    <script>
   <?php
}

Using a check variable

Since the subscribe method will run every time something has changed, it will also run when we lock the post saving button. If we don’t use a check variable for it, we will create an infinite loop.

var postLocked = false;
wp.domReady( () => {
   // DOM is Ready, let's code everything else here.
});

We will use the postLocked variable to check if we already locked it or not. This will be the check variable so we don’t trigger a change again.

Locking and unlocking the Post Saving button

Let’s now see how we can lock or unlock the button.

var postLocked = false;
wp.domReady( () => {

  wp.data.subscribe(function(){
    // Featured Image ID.
    var imageId = wp.data.select( 'core/editor' ).getEditedPostAttribute('featured_media');

    // If we have no image ID, and we already locked the post, we won't do anything.
    if ( ! imageId ) {

       // No Image ID and post is not locked. Let's lock it.
       if ( ! postLocked ) {
               postLocked = true;
               wp.data.dispatch('core/editor').lockPostSaving('noFeaturedImage');
                       
        }
     } else if (postLocked) {
        postLocked = false;
        wp.data.dispatch( 'core/editor' ).unlockPostSaving( 'noFeaturedImage' );                 
     }

   });

});

That’s it! You might be wondering why I did not put ! imageID && ! postLocked. I did it like that because I want it to go inside of the IF statement if there is no imageId. Why? Because we might have already locked the post and that’s fine.

If I had put it together, it would go straight to else if statement and unlock it. We don’t want that.

Showing a “Add Featured Image to Publish” Notice

We will now change the code a bit by adding a notice at the top bar of the Block Editor. This will use the vanilla JavaScript DOM methods to add or remove HTML. Nothing special, but provides a better user experience.

This part is available only to the members. If you want to become a member and support my work go to this link and subscribe: Become a Member

Conclusion

By using the wp.data store manager, we can control several aspects of the block editor and also change the user experience for our clients or ourselves.

It takes time to learn what can be done with it, but it’s possible and don’t be afraid to search the code of the Block Editor. That’s the best way to learn it.

Become a Sponsor

Posted by Igor Benic

Web Developer who mainly uses WordPress for projects. Working on various project through Codeable & Toptal. Author of several ebooks at https://leanpub.com/u/igorbenic.

Leave a reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.